/**
 * Copyright (c) 2010 Sense Tecnic Systems Inc.
 */
package com.testcase.vincentApp;

import java.util.Date;
import java.util.Observable;
import java.util.Observer;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
import android.location.LocationManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.format.DateUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.testcase.vincentApp.SensorManager.SensorUpdated;
import com.testcase.R;

/**
 * Activity for the preference page in this application.
 * 
 * @author Vincent Tsao
 */
public class AndroidSensors extends Activity implements Observer
{
	// used for debug logs
	static final String TAG = "AndroidSensors";

	private static final int ABOUT_DIALOG_ID = 0;

	private static final float SENSOR_HEADING_SIZE = 36;
	private static final float SENSOR_READING_SIZE = 28;
	private static final float SENSOR_TS_SIZE = 11;
	
	private LocationManager locationManager;
	private android.hardware.SensorManager androidSensorManager;

	private Resources resources;
	private SharedPreferences preferences;
	private SensorManager sensorManager;

	@Override
	protected void onCreate (Bundle savedInstanceState)
	{
		super.onCreate (savedInstanceState);

		// create the ui
		setContentView (R.layout.vincent_main);
		initUI ();

		// get the location manager
		locationManager = (LocationManager) getSystemService (LOCATION_SERVICE);

		// get the sensor manager
		androidSensorManager = (android.hardware.SensorManager) getSystemService (SENSOR_SERVICE);

		resources = getResources ();
		preferences = PreferenceManager.getDefaultSharedPreferences (this);
		sensorManager = SensorManager.getSensorManager ();
		sensorManager.initSensorManager (resources, preferences, locationManager, androidSensorManager);
		sensorManager.addObserver (this);

		// start the sensor update daemon if it's active
		boolean isActive = preferences.getBoolean (resources.getString (R.string.isActiveKey), true);

		if (isActive)
			sensorManager.startSensorUpdates ();
	}

	@Override
	protected void onStart ()
	{
		super.onStart ();
	}

	@Override
	protected void onRestart ()
	{
		super.onRestart ();
	}

	@Override
	protected void onResume ()
	{
		super.onResume ();

		updateTimestamps ();
	}

	@Override
	protected void onPause ()
	{
		super.onPause ();
	}

	@Override
	protected void onStop ()
	{
		super.onStop ();
	}

	@Override
	protected void onDestroy ()
	{
		super.onDestroy ();
	}

	@Override
	public boolean onCreateOptionsMenu (Menu menu)
	{
		MenuInflater inflater = getMenuInflater ();
		inflater.inflate (R.menu.vincent_main_menu, menu);

		return true;
	}

	@Override
	public boolean onOptionsItemSelected (MenuItem item)
	{
		switch (item.getItemId ())
		{
			case R.id.settings:
				Intent i = new Intent (this, Preferences.class);
				startActivity (i);
				return true;

			case R.id.about:
				showDialog (ABOUT_DIALOG_ID);
				return true;

			default:
				return super.onOptionsItemSelected (item);
		}
	}

	private void initUI ()
	{
		HorizontalPagingScrollView sensorUpdates = (HorizontalPagingScrollView) findViewById (R.id.LatestReadings);

		// TODO: vtsao - the lines parameter are a hack and hardcoded here, at
		// least they should be constants?
		addSensorUpdate (sensorUpdates, R.string.location, R.id.locReading, R.id.locReadingTs, 2);
		addSensorUpdate (sensorUpdates, R.string.accelerometer, R.id.accReading, R.id.accReadingTs, 1);
		addSensorUpdate (sensorUpdates, R.string.magnetometer, R.id.magReading, R.id.magReadingTs, 1);
		addSensorUpdate (sensorUpdates, R.string.light, R.id.lightReading, R.id.lightReadingTs, 1);
	}

	private void addSensorUpdate (HorizontalPagingScrollView sensorNames, int sensorNameId, int sensorReadingId, int timestampId, int lines)
	{
		TextView sensorName = new TextView (getApplicationContext ());
		sensorName.setText (getResources ().getString (sensorNameId));
		sensorName.setTextColor (ColorStateList.valueOf (Color.BLACK));
		sensorName.setTextSize (SENSOR_HEADING_SIZE);

		TextView sensorReading = new TextView (getApplicationContext ());
		sensorReading.setId (sensorReadingId);
		sensorReading.setText (getResources ().getString (R.string.noReading));
		sensorReading.setTextColor (ColorStateList.valueOf (Color.BLACK));
		sensorReading.setTextSize (SENSOR_READING_SIZE);

		// TODO: vtsao - because we know how many values each sensor value needs
		// we can set it here so that the height of the textview will be right,
		// I couldn't find a better way of automatically having the textview
		// adjust its height to fit all the text (ie: I couldn't figure it out)
		sensorReading.setLines (lines);

		TextView timestamp = new TextView (getApplicationContext ());
		timestamp.setId (timestampId);
		timestamp.setTextColor (ColorStateList.valueOf (Color.GRAY));
		timestamp.setTextSize (SENSOR_TS_SIZE);

		LinearLayout sensorUpdate = new LinearLayout (getApplicationContext ());
		sensorUpdate.setId (R.id.sensorUpdate);
		sensorUpdate.setOrientation (LinearLayout.VERTICAL);
		sensorUpdate.addView (sensorName);
		sensorUpdate.addView (sensorReading);
		sensorUpdate.addView (timestamp);
		sensorNames.addView (sensorUpdate);
	}

	/**
	 * TODO: vtsao - poor mvc in Android, should be using a content provider,
	 * but this is quick and dirty
	 */
	public void update (Observable observable, Object data)
	{
		SensorUpdated sensorUpdated = (SensorUpdated) data;

		switch (sensorUpdated)
		{
			case LOC:

				Double latValue = sensorManager.getLatestLat ();
				Double lngValue = sensorManager.getLatestLng ();

				TextView locReading = (TextView) findViewById (R.id.locReading);
				locReading.setText (latValue + "\n" + lngValue);

				break;

			case ACC:

				Double accValue = sensorManager.getLatestAcc ();
				TextView accReading = (TextView) findViewById (R.id.accReading);
				accReading.setText (accValue + "");

				break;

			case MAG:
				break;

			case LIGHT:
				break;
		}

		updateTimestamps ();

		// refresh the textview
		findViewById (R.id.sensorUpdate).postInvalidate ();
	}

	@Override
	protected Dialog onCreateDialog (int id)
	{
		Dialog dialog = null;

		switch (id)
		{
			case ABOUT_DIALOG_ID:

				AlertDialog.Builder builder = new AlertDialog.Builder (this);
				builder.setMessage (resources.getString (R.string.about)).setCancelable (false).setNeutralButton (R.string.okayDesuKa, new DialogInterface.OnClickListener ()
				{
					public void onClick (DialogInterface dialog, int which)
					{
						dialog.cancel ();
					}
				});

				dialog = builder.create ();

				break;
		}

		return dialog;
	}

	private void updateTimestamps ()
	{
		long now = System.currentTimeMillis ();

		Date locTsValue = sensorManager.getLatestLocTs ();

		if (locTsValue != null)
		{
			TextView locTs = (TextView) findViewById (R.id.locReadingTs);
			locTs.setText (DateUtils.getRelativeTimeSpanString (locTsValue.getTime (), now, DateUtils.SECOND_IN_MILLIS));
		}

		Date accTsValue = sensorManager.getLatestAccTs ();

		if (accTsValue != null)
		{
			TextView accTs = (TextView) findViewById (R.id.accReadingTs);
			accTs.setText (DateUtils.getRelativeTimeSpanString (accTsValue.getTime (), now, DateUtils.SECOND_IN_MILLIS));
		}
	}
}